#include<iostream>
#include <cstdlib>
#include<string>
#include<stack>
#define LENGTH 512

using namespace std;

void ReadNum(const char &tmp);
void Bracket();
void Calculate(const char &op);
void OpPriority(const char &tmp);


template <typename T>
class MyStack{
private:
    T* start;
    T* top;
    int len;

public:
    MyStack(){
        start = new T[LENGTH];
        top = start - 1;
        len = LENGTH;
    }

    ~MyStack(){
        free(start);
    }

    T _top(){return *top;}

    bool isempty(){
        if(top <start) {return true;}
        return false;
    }

    T pop(){return *top--;}

    void push(T _c){
        if((top -start) >= len)
        {
            start = (T*)realloc(start,(len+LENGTH)*sizeof(T));
            top = start+LENGTH;
            len += LENGTH;
        }
        else{
            top++;
            *top = _c;
        }
    }

    int TopPriority(){
        if(*top == '('){return 0;}
        else if(*top == '*' || *top == '/'){return 2;}
        return 1;
    }
};

MyStack<char> BrackerStack;
MyStack<float> NumStack;

float integer = 0;
float decimal = 0;
bool dot = false;
bool Num = false;

void ResetNum(){
    integer = 0;
    decimal = 0;
    dot = false;
    Num = false;
}

void ReadNum(const char &tmp){
    char pd = tmp;
    if(pd == '.'){
        if(!Num)
        {
            cout<<"Error, No number before . "<<endl;
            exit(0);
        }
        if(dot){
            cout<<"Error, . appeard twice "<<endl;
            exit(0);
        }
        dot = true;
    }
    else if (!dot) {
        integer *= 10;
        integer += pd - '0';
    }
    else {
        decimal *= 10;
        decimal += pd - '0';
    }
    Num = true;    
}

void PushNum(){
    if(!dot){
        float num = integer;
        NumStack.push(num);
    }
    else{
         while (decimal >= 1) {
            decimal=decimal / 10;
        }
        float num = (float)integer+decimal;
        NumStack.push(num);
    }
}

void Bracket(){
    if(BrackerStack.isempty()) return;
    char op = BrackerStack.pop();
    while(op!='('){
        Calculate(op);
        if(!BrackerStack.isempty())
            op = BrackerStack.pop();
        else
            return;
    }
}

void OpPriority(const char &tmp){
    int priority = 1;
    char op;
    if(tmp == '*'||tmp == '/')
        priority = 2;
    
    while(!(BrackerStack.isempty()||BrackerStack.TopPriority()<priority)){
        op = BrackerStack.pop();
        Calculate(op);
    }
    BrackerStack.push(tmp);
}

void Calculate(const char &op)
{
    float num2 = NumStack.pop();
    float num1 = NumStack.pop();
    float ans = 0;
    switch (op)
    {
    case '+':
        ans = num1 + num2;
        break;
    case '-':
        ans = num1 - num2;
        break;
    case '*':
        ans = num1 * num2;
        break;
    case '/':
        ans = num1 / num2;
        break;
    }
    NumStack.push(ans);
}

bool isoperator(const char &tmp){
    return !((tmp!='(')&&(tmp!=')')&&(tmp != '+')&&(tmp != '-')&&(tmp!='*')&&(tmp!='/'));
}
